package com.app.library.utils

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import com.app.library.base.LibViewModel
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.ParameterizedType

object ViewModelUtils {

    fun getBaseViewModel(activity: FragmentActivity): LibViewModel {
        return ViewModelProvider(activity)[LibViewModel::class.java]
    }

    fun getBaseViewModel(fragment: Fragment): LibViewModel {
        return ViewModelProvider(fragment)[LibViewModel::class.java]
    }

    @JvmStatic
    fun <VM : LibViewModel> getWithGeneric(owner: ViewModelStoreOwner): VM =
        ViewModelProvider(owner)[withGenericModelClass(owner)]

    private fun <VM : LibViewModel> withGenericModelClass(owner: ViewModelStoreOwner): Class<VM> {
        var genericSuperclass = owner.javaClass.genericSuperclass
        var superclass = owner.javaClass.superclass
        while (superclass != null) {
            if (genericSuperclass is ParameterizedType) {
                try {
                    if (genericSuperclass.actualTypeArguments.size > 1) {
                        return genericSuperclass.actualTypeArguments[1] as Class<VM>
                    }
                } catch (e: NoSuchMethodException) {
                } catch (e: ClassCastException) {
                } catch (e: Exception) {
                    var tagException: Throwable? = e
                    while (tagException is InvocationTargetException) {
                        tagException = e.cause
                    }
                    throw tagException
                        ?: IllegalArgumentException("ViewBinding generic was found, but creation failed.")
                }
            }
            genericSuperclass = superclass.genericSuperclass
            superclass = superclass.superclass
        }
        throw IllegalArgumentException("There is no generic of ViewBinding.")
    }
}